﻿package net.wangit;

import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.wangit.jdbc.JDBCException;
import net.wangit.jdbc.sqltype.SqlType;
import net.wangit.jdbc.sqltype.SqlTypeFactory;
import net.wangit.util.StringUtil;


/**
 * 数据集合，用于单元数据和枚举数据。 数据结构为：
 *  0 1 2 ...(列序号) 
 *  key0 key1 key2 ...(名称) 
 *  0 值 值 值
 *  1 值 值 值 
 *  2 值 值 值 
 *  ...(行序号)
 * 
 * @author watson Feb 24, 2010
 */
@SuppressWarnings("serial")
public class MapList implements Serializable {
	private List<Row> list;
	private Map<String, Integer> mapping1;
	private HashMap<Integer, String> mapping2;

	public MapList() {
		list = new ArrayList<Row>();
		mapping1 = new HashMap<String, Integer>();
		mapping2 = new HashMap<Integer, String>();
	}

	// 在指定行设置数据。
	public void put(int rowIndex, String key, String value) {
		Row row = addRow(rowIndex);
		row.put(key, value);
	}

	public Row addRow(int rowIndex) {
		Row row = null;
		for (int i = size(); i <= rowIndex; i++) {
			row = new Row(mapping1, mapping2);
			list.add(row);
		}

		return row != null ? row : (Row) list.get(rowIndex);
	}

	// 在指定行设置数据。
	public void put(int rowIndex, String key, int value) {
		put(rowIndex, key, Integer.toString(value));
	}

	// 在指定行设置数据。
	public void put(int rowIndex, String key, long value) {
		put(rowIndex, key, Long.toString(value));
	}

	// 在指定行设置数据。
	public void put(int rowIndex, String key, float value) {
		put(rowIndex, key, Float.toString(value));
	}

	// 在指定行设置数据。
	public void put(int rowIndex, String key, double value) {
		put(rowIndex, key, Double.toString(value));
	}

	// 追加数据，加入list对象的所有数据。
	public void add(MapList list) {
		Set<String> keySet = list.mapping1.keySet();
		int index = size();
		for (int i = 0; i < list.size(); i++) {
			String key;
			String value;
			Iterator<String> keys = keySet.iterator();
			while (keys.hasNext()) {
				key = keys.next();
				value = list.getRow(i).get(key);
				put(index + i, key, value);
			}

		}

	}

	// 追加数据，row为null时插入一个空行。
	public void add(Row row) {
		insertRow(size(), row != null ? row.toMap() : null);
	}

	// 复制列，创建一个新列key2，并复制key1的所有数据。
	public void copyColumn(String key1, String key2) {
		for (int i = 0; i < size(); i++)
			put(i, key2, getRow(i).get(key1));

	}

	// 在指定位置插入一行，row为null时插入一个空行。
	public void insertRow(int rowIndex, Row row) {
		insertRow(rowIndex, row != null ? row.toMap() : null);
	}

	// 在指定位置插入一行，包含map的所有数据，map为null时插入一个空行。
	public void insertRow(int rowIndex, Map<String, String> map) {
		Row row;
		if (rowIndex > size()) {
			row = addRow(rowIndex);
		} else {
			row = new Row(mapping1, mapping2);
			list.add(rowIndex, row);
		}
		if (map != null) {
			Set<String> keySet = map.keySet();
			String key;
			String value;
			Iterator<String> keys = keySet.iterator();
			while (keys.hasNext()) {
				key = keys.next();
				value = map.get(key);
				row.put(key, value);
			}
		}
	}

	// 删除指定行，行序号非法时不作任何操作。
	public void removeRow(int rowIndex) {
		if (rowIndex >= 0 && rowIndex < list.size())
			list.remove(rowIndex);
	}

	// 删除指定名称为指定值的第一个行，找不到时没有操作。
	public void removeRow(String key, String value) {
		int rowIndex = findRowIndex(key, value);
		list.remove(rowIndex);
	}

	// 找指定名称为指定值的第一个行的序号
	public int findRowIndex(String key, String value) {
		for (int i = 0; i < size(); i++) {
			String v = get(i, key);
			if (value != null && value.equals(v) || v != null
					&& v.equals(value) || v == null && value == null)
				return i;
		}

		return -1;
	}

	// 查找指定名称为指定值的第一个行
	public Row findRow(String key, String value) {
		int index = findRowIndex(key, value);
		return index >= 0 ? getRow(index) : null;
	}

	// 找指定名称数组和指定值数组对应的第一个行的序号
	public int findRowIndex(String keys[], String values[]) {
		for (int i = 0; i < size(); i++) {
			boolean found = true;
			for (int j = 0; j < values.length; j++) {
				String v = get(i, keys[j]);
				if ((values[j] == null || values[j].equals(v))
						&& (v == null || v.equals(values[j]))
						&& (v != null || values[j] == null))
					continue;
				found = false;
				break;
			}

			if (found)
				return i;
		}

		return -1;
	}

	// 查找指定名称数组和指定值数组对应的第一个行
	public Row findRow(String keys[], String values[]) {
		int index = findRowIndex(keys, values);
		return index >= 0 ? getRow(index) : null;
	}

	// 查找指定行中为指定值的第一个列序号
	public int findColumnIndex(Row row, String value) {
		for (int i = 0; i < row.size(); i++) {
			String v = row.get(i);
			if (value != null && value.equals(v) || v != null
					&& v.equals(value) || v == null && value == null)
				return i;
		}

		return -1;
	}

	private String get(int rowIndex, String key) {
		if (rowIndex < 0 || rowIndex >= size()) {
			return null;
		} else {
			Row row = getRow(rowIndex);
			return row.get(key);
		}
	}

	private String get(int rowIndex, int columnIndex) {
		if (rowIndex < 0 || rowIndex >= size()) {
			return null;
		} else {
			Row row = getRow(rowIndex);
			return row.get(columnIndex);
		}
	}

	// 取得行数
	public int size() {
		return list.size();
	}

	// 取得列数
	public int width() {
		return mapping1.size();
	}

	// 打印所有数据，输出到控制台。
	public void print() {
		try {
			int columnLengths[] = new int[width()];
			for (int j = 0; j < width(); j++) {
				int maxLength = 0;
				for (int i = 0; i < size(); i++) {
					String value = get(i, j);
					value = value != null ? value : "";
					int length = value.getBytes().length;
					maxLength = length <= maxLength ? maxLength : length;
				}

				columnLengths[j] = maxLength;
			}

			StringBuffer sb = new StringBuffer("\n    ");
			for (int j = 0; j < width(); j++) {
				int length = getKey(j).getBytes().length;
				columnLengths[j] = (length <= columnLengths[j] ? columnLengths[j]
						: length) + 2;
				sb.append(StringUtil.fill(getKey(j), columnLengths[j], ' ',
						true));
			}

			for (int i = 0; i < size(); i++) {
				sb.append("\n").append(
						StringUtil.fill(Integer.toString(i), 4, ' ', true));
				for (int j = 0; j < width(); j++) {
					String value = get(i, j);
					value = value != null ? value : "";
					sb.append(StringUtil.fill(value, columnLengths[j], ' ',
							true));
				}

			}

			System.out.println(sb);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// 取得行对象。
	public Row getRow(int rowIndex) {
		if (rowIndex < 0 || rowIndex >= size()) {
			return null;
		} else {
			Row row = list.get(rowIndex);
			row.setIndex(rowIndex);
			return row;
		}
	}

	private String getKey(int index) {
		return (String) mapping2.get(new Integer(index));
	}

	// 由ResultSet生成MapList对象
	private static MapList getMapList(ResultSet rs) throws SQLException,
			JDBCException {
		ResultSetMetaData meta = rs.getMetaData();
		int columnCount = meta.getColumnCount();
		String[] names = new String[columnCount];
		SqlType sqlTypes[] = new SqlType[columnCount];
		for (int i = 1; i <= columnCount; i++) {
			names[i - 1] = meta.getColumnName(i).toLowerCase();
			sqlTypes[i - 1] = SqlTypeFactory.getSqlType(meta.getColumnType(i));
		}

		MapList list = new MapList();
		for (int count = 0; rs.next(); count++) {
			for (int i = 0; i < columnCount; i++)
				list.put(count, names[i], sqlTypes[i].get(rs, names[i]));

		}

		return list;
	}

	// 按指定的最大行数分解为多个MapList，最大行数<=0时，List中只包含一个原MapList。
	private List<MapList> split(int size) {
		List<MapList> datas = new ArrayList<MapList>();
		if (size() == 0 || size <= 0) {
			datas.add(this);
			return datas;
		}
		int count = 0;
		MapList data = new MapList();
		for (int i = 0; i < size(); i++) {
			data.insertRow(count, getRow(i).toMap());
			if (++count == size) {
				datas.add(data);
				data = new MapList();
				count = 0;
			}
		}

		datas.add(data);
		return datas;
	}
}
